package com.wenjie.original.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Sets;
import com.mybatisflex.core.query.QueryWrapper;
import com.wenjie.common.utils.TokenUtil;
import com.wenjie.original.entity.*;
import com.wenjie.original.entity.common.vo.RestBaseVo;
import com.wenjie.original.entity.table.OrderBoxAuthorityTableDef;
import com.wenjie.original.entity.table.ScanRecordTableDef;
import com.wenjie.original.entity.vo.ScanRecord.ScanRecordUpOrAddVo;
import com.wenjie.original.entity.vo.ScanRecord.ScanRecordVo;
import com.wenjie.original.flex_config.baseInterface.Cus_ServiceImp;
import com.wenjie.original.mapper.ScanRecordMapper;
import com.wenjie.original.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;


@Service
public class ScanRecordServiceImpl extends Cus_ServiceImp<ScanRecordMapper, ScanRecord> implements IScanRecordService {


    @Autowired
    private ISkuService skuService;

    @Autowired
    private IBoxService boxService;

    @Autowired
    private IOrderService orderService;

    @Autowired
    private ICodeListService codeListService;

    @Autowired
    private IOrderBoxAuthorityService orderBoxAuthorityService;

    @Autowired
    private IOrderBoxService orderBoxService;


    @Override
    public List<ScanRecord> detail(Long scanRecordId) {
        ScanRecord scanRecord = this.getById(scanRecordId);
        ScanRecord top = findTop(scanRecord);
        return this.listByIds(top.getScanGroups());
    }

    /**
     * @Description 查询到最上层的数据
     * @author wenjie
     * @date 2024/11/11 11:47
     */
    private ScanRecord findTop(ScanRecord scanRecord) {
        if (scanRecord.getParentScanRecordId() == null) {
            return scanRecord;
        } else {
            return findTop(this.getById(scanRecord.getParentScanRecordId()));
        }
    }


    @Override
    @Transactional
    public void saveSmall(ScanRecordUpOrAddVo.AddSmallVo addVo) {

        // 判断条码是否存在 状态是否是未使用
        CodeList codeList = codeListService.getbyCode(addVo.getCode());
        if (codeList == null || !codeList.getCodeListStatus().getCode().equals(CodeList.CODE_LIST_STATUS.arg1.getCode())) {
            throw new RuntimeException("箱号不正确");
        }

        OrderBox orderBox = orderBoxService.getById(addVo.getOrderBoxId());
        List<OrderBox> orderBoxs = orderBoxService.getByOrderId(orderBox.getOrderId());

        // 判断一下当前的箱子需要的装箱数量
        Integer orderBoxNeedNum = getOrderBoxNeedNum(orderBoxs, orderBox.getOrderBoxBySequence());

        // 判断一下 打包的数量
        if (!addVo.getScanNum().equals(orderBox.getOrderBoxByBoxNum())) {
            throw new RuntimeException("当前的计划装箱数量和实际装箱数量不匹配,请确定装箱数量");
        }

        // 判断一下 重量范围
        BigDecimal low = new BigDecimal(orderBox.getOrderBoxByBoxLowWeight());
        BigDecimal hight = new BigDecimal(orderBox.getOrderBoxByBoxHighWeight());
        BigDecimal weight = new BigDecimal(addVo.getScanWeight());
        if (weight.compareTo(low) < 0 || weight.compareTo(hight) > 0) {
            throw new RuntimeException("当前的重量范围不正确");
        }

        // 判断一下记录数量
        long count = this.count(QueryWrapper.create().where(ScanRecordTableDef.SCAN_RECORD.ORDER_BOX_ID.eq(orderBox.getOrderBoxId())));
        if (count >= orderBoxNeedNum) {
            throw new RuntimeException("当前订单次打包计划 打包数量超出计划数量");
        }

        // 修改一下编号信息的状态
        codeList.setCodeListStatus(CodeList.CODE_LIST_STATUS.arg2);
        codeListService.updateById(codeList);


        // 直接记录数据，不在保留状态，而且不在保留商品信息等信息
        Order orderInfo = orderService.getById(orderBox.getOrderId());
        Sku skuInfo = skuService.getById(orderInfo.getSkuId());
        Box boxInfo = boxService.getById(orderBox.getBoxId());

        ScanRecord scanRecord = new ScanRecord();

        scanRecord.setScanRecordId(IdUtil.getSnowflakeNextId());
        scanRecord.setOrderId(orderInfo.getOrderId());
        scanRecord.setBoxId(boxInfo.getBoxId());
        scanRecord.setSkuId(skuInfo.getSkuId());
        scanRecord.setOrderBoxId(orderBox.getOrderBoxId());

        scanRecord.setCode(codeList.getCode());
        scanRecord.setOrderName(orderInfo.getOrderName());
        scanRecord.setOrderKey(orderInfo.getOrderKey());
        scanRecord.setSkuName(skuInfo.getSkuName());
        scanRecord.setSkuBarCode(skuInfo.getSkuBarCode());
        scanRecord.setBoxName(boxInfo.getBoxName());
        scanRecord.setBoxBarCode(boxInfo.getBoxBarCode());
        scanRecord.setOrderBoxByBoxLowWeight(orderBox.getOrderBoxByBoxLowWeight());
        scanRecord.setOrderBoxByBoxHighWeight(orderBox.getOrderBoxByBoxHighWeight());
        scanRecord.setOrderBoxBySequence(orderBox.getOrderBoxBySequence());
        scanRecord.setScanGroups(Sets.newHashSet(scanRecord.getScanRecordId()));
        scanRecord.setScanType(ScanRecord.SCAN_TYPE.arg1);
        scanRecord.setScanNum(addVo.getScanNum());
        scanRecord.setScanWeight(addVo.getScanWeight());
        scanRecord.setOrderInfo(JSONUtil.toJsonStr(orderInfo));
        scanRecord.setSkuInfo(JSONUtil.toJsonStr(skuInfo));
        scanRecord.setBoxInfo(JSONUtil.toJsonStr(boxInfo));
        scanRecord.setOrderBoxInfo(JSONUtil.toJsonStr(orderBox));
        this.save(scanRecord);
    }


    @Override
    @Transactional
    public void saveBig(ScanRecordUpOrAddVo.AddBigVo addVo) {
        Long scanRecordId = IdUtil.getSnowflakeNextId();
        // 判断条码是否存在 状态是否是未使用
        CodeList codeList = codeListService.getbyCode(addVo.getCode());
        if (codeList == null || !codeList.getCodeListStatus().getCode().equals(CodeList.CODE_LIST_STATUS.arg1.getCode())) {
            throw new RuntimeException("箱号不正确");
        }

        OrderBox orderBox = orderBoxService.getById(addVo.getOrderBoxId());
        List<OrderBox> orderBoxs = orderBoxService.getByOrderId(orderBox.getOrderId());

        // 判断一下当前的箱子需要的装箱数量
        Integer orderBoxNeedNum = getOrderBoxNeedNum(orderBoxs, orderBox.getOrderBoxBySequence());


        // 判断一下 重量范围
        BigDecimal low = new BigDecimal(orderBox.getOrderBoxByBoxLowWeight());
        BigDecimal hight = new BigDecimal(orderBox.getOrderBoxByBoxHighWeight());
        BigDecimal weight = new BigDecimal(addVo.getScanWeight());
        if (weight.compareTo(low) < 0 || weight.compareTo(hight) > 0) {
            throw new RuntimeException("当前的重量范围不正确");
        }

        // 判断一下记录数量
        long count = this.count(QueryWrapper.create().where(ScanRecordTableDef.SCAN_RECORD.ORDER_BOX_ID.eq(orderBox.getOrderBoxId())));
        if (count > orderBoxNeedNum) {
            throw new RuntimeException("当前订单次打包计划 打包数量超出计划数量");
        }


        // 判断一下 打包的数量
        if (!orderBox.getOrderBoxByBoxNum().equals(addVo.getScanRecordIds().size())) {
            throw new RuntimeException("当前的计划装箱数量和实际装箱数量不匹配,请确定装箱数量");
        }

        // 判断一下子打包计划的状态
        List<ScanRecord> scanRecords = this.listByIds(addVo.getScanRecordIds());
        if (addVo.getScanRecordIds().size() != scanRecords.size()) {
            throw new RuntimeException("子包装记录，读取数量不正确，请联系开发人员解决");
        }
        for (ScanRecord scanRecord : scanRecords) {
            if (scanRecord.getParentScanRecordId() != null) {
                throw new RuntimeException("存在子包装已经包装过");
            }
            scanRecord.setParentScanRecordId(scanRecordId);
        }
        this.updateBatch(scanRecords); // 在子扫码记录中，记录父扫码记录的id

        //  获取一下全部的字记录包括自身
        Set<Long> scanGroups = new HashSet<>();
        for (ScanRecord scanRecord : scanRecords) {
            scanGroups.addAll(scanRecord.getScanGroups());
        }
        scanGroups.add(scanRecordId);


        // 修改一下编号信息的状态
        codeList.setCodeListStatus(CodeList.CODE_LIST_STATUS.arg2);
        codeListService.updateById(codeList);


        // 直接记录数据，不在保留状态，而且不在保留商品信息等信息
        Order orderInfo = orderService.getById(orderBox.getOrderId());
        Sku skuInfo = skuService.getById(orderInfo.getSkuId());
        Box boxInfo = boxService.getById(orderBox.getBoxId());

        ScanRecord scanRecord = new ScanRecord();

        scanRecord.setScanRecordId(scanRecordId);
        scanRecord.setOrderId(orderInfo.getOrderId());
        scanRecord.setBoxId(boxInfo.getBoxId());
        scanRecord.setSkuId(skuInfo.getSkuId());
        scanRecord.setOrderBoxId(orderBox.getOrderBoxId());

        scanRecord.setCode(codeList.getCode());
        scanRecord.setOrderName(orderInfo.getOrderName());
        scanRecord.setOrderKey(orderInfo.getOrderKey());
        scanRecord.setSkuName(skuInfo.getSkuName());
        scanRecord.setSkuBarCode(skuInfo.getSkuBarCode());
        scanRecord.setBoxName(boxInfo.getBoxName());
        scanRecord.setBoxBarCode(boxInfo.getBoxBarCode());
        scanRecord.setOrderBoxByBoxLowWeight(orderBox.getOrderBoxByBoxLowWeight());
        scanRecord.setOrderBoxByBoxHighWeight(orderBox.getOrderBoxByBoxHighWeight());
        scanRecord.setOrderBoxBySequence(orderBox.getOrderBoxBySequence());
        scanRecord.setScanGroups(scanGroups);
        scanRecord.setScanType(ScanRecord.SCAN_TYPE.arg2);
        scanRecord.setScanNum(addVo.getScanRecordIds().size());
        scanRecord.setScanWeight(addVo.getScanWeight());
        scanRecord.setOrderInfo(JSONUtil.toJsonStr(orderInfo));
        scanRecord.setSkuInfo(JSONUtil.toJsonStr(skuInfo));
        scanRecord.setBoxInfo(JSONUtil.toJsonStr(boxInfo));
        scanRecord.setOrderBoxInfo(JSONUtil.toJsonStr(orderBox));
        this.save(scanRecord);
    }

    @Override
    public Boolean checkAuthority(Long orderBoxId) {
        Long id = TokenUtil.getTokenInfo().getId();

        OrderBoxAuthority one = orderBoxAuthorityService.getOne(QueryWrapper.create().where(OrderBoxAuthorityTableDef.ORDER_BOX_AUTHORITY.ORDER_BOX_ID.eq(orderBoxId).and(OrderBoxAuthorityTableDef.ORDER_BOX_AUTHORITY.SYS_ADMIN_ID.eq(id))));
        if (one == null) return false;
        else return true;
    }

    @Override
    public RestBaseVo<ScanRecordVo.ResVo> getByCodeByBigScan(ScanRecordVo.getByCodeByBigScanSelVo selVo, Class<ScanRecordVo.ResVo> resVoClass) {


        return null;
    }


    private Integer getOrderBoxNeedNum(List<OrderBox> orderBoxs, Integer sequence) {

        Collections.sort(orderBoxs, new Comparator<OrderBox>() {
            @Override
            public int compare(OrderBox o1, OrderBox o2) {
                return o1.getOrderBoxBySequence().compareTo(o2.getOrderBoxBySequence());
            }
        });


        if (sequence.equals(1)) {
            if (orderBoxs.get(0).getOrderBoxBySequence().equals(1)) {
                return orderBoxs.get(0).getOrderBoxByBoxNum();
            }
        } else {

            Integer resNum = 1;
            for (OrderBox orderBox : orderBoxs) {
                if (orderBox.getOrderBoxBySequence().equals(sequence)) {
                    resNum = resNum * orderBox.getOrderBoxByBoxNum();
                    return resNum;
                } else {
                    resNum = resNum * orderBox.getOrderBoxByBoxNum();
                }
            }
        }
        throw new RuntimeException("打包计划数据不正确,请联系开发排查");
    }


}
